package credit.ccx.com.walletcore.helper;

import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.admin.AdminFactory;
import org.web3j.protocol.admin.methods.response.PersonalUnlockAccount;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;

/**
 * Created by gongdongyang on 2018/7/12.
 */

public class TransferHelper {

    /**
     * 地址转账
     * @param from
     * @param password
     * @param to
     * @param value
     * @return
     * @throws Exception
     */
    public static String transferEth(String from, String password, String to, BigInteger value) throws Exception {
        //Web3j web3j = Web3jFactory.build(new HttpService("http://10.0.5.43:8101/"));
        Admin web3j = AdminFactory.build(new HttpService("http://10.0.5.43:8101/"));

        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                from, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount(from, password).send();
        if (personalUnlockAccount.accountUnlocked()) {
            BigInteger gasPrice = Contract.GAS_PRICE;
            BigInteger gasLimit = new BigInteger("90000");
            synchronized (TransferHelper.class) {
                BigInteger eth_value = new BigInteger("1000000000000000000").multiply(value);
                Transaction transaction = Transaction.createEtherTransaction(from, nonce, gasPrice, gasLimit, to, eth_value);
                EthSendTransaction transactionResponse = web3j.ethSendTransaction(transaction).sendAsync().get();
                if (transactionResponse.hasError()) {

                    String message=transactionResponse.getError().getMessage();
                    System.out.println("transaction failed,info:"+message);
                    return message;

                }else{
                    String hash=transactionResponse.getTransactionHash();
                    EthGetTransactionReceipt send = web3j.ethGetTransactionReceipt(hash).send();
                    System.out.println("transaction from "+from+" to "+to+" amount:"+eth_value);
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                    BigInteger gas_quility = web3j.ethEstimateGas(transaction).send().getAmountUsed();
                    BigInteger gas_price = web3j.ethGasPrice().send().getGasPrice();
                    BigInteger bgasUsed = gas_quility.multiply(gas_price);
                    BigDecimal gasUsed = Convert.fromWei(bgasUsed.toString(), Convert.Unit.ETHER);
                    System.out.println("transaction gas_quility:"+gas_quility+",gas_price:"+gas_price+",gasUsed:"+gasUsed);
                    return  hash;
                }
            }
        }
        return "";
    }


    /**
     * Keystore转账
     * @param password
     * @param keyStore
     * @param to
     * @param value
     * @return
     * @throws Exception
     */
    public static String localSendEther(String password,String keyStore,String to,BigInteger value) throws Exception{

        Credentials credentials = WalletUtils.loadCredentials(password,keyStore);
        Admin web3j = AdminFactory.build(new HttpService("http://10.0.5.43:8101/"));
        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                credentials.getAddress(), DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        BigInteger gasPrice = new BigInteger("120000000000");
        BigInteger gasLimit = Contract.GAS_LIMIT.divide(new BigInteger("2"));
        BigInteger eth_value = new BigInteger("1000000000000000000").multiply(value);

        //生成RawTransaction交易对象
        RawTransaction rawTransaction  = RawTransaction.createTransaction(nonce,gasPrice,gasLimit,to,eth_value,"abcde123");//可以额外带数据

        //使用Credentials对象对RawTransaction对象进行签名
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction,credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
        String transactionHash = ethSendTransaction.getTransactionHash();

        if(ethSendTransaction.hasError()){
            String message=ethSendTransaction.getError().getMessage();
            System.out.println("transaction failed,info:"+message);
            return message;
        }else{
            String hash = ethSendTransaction.getTransactionHash();
            EthGetTransactionReceipt send = web3j.ethGetTransactionReceipt(hash).send();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return hash;
        }

    }
}
